package com.kintreda.ieco_server.core.web;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.kintreda.ieco_server.bean.account.User;
import com.kintreda.ieco_server.core.service.RedisService;
import com.kintreda.ieco_server.util.Assert;
import com.kintreda.ieco_server.util.UserSession;
import com.kintreda.ieco_server.util.redis.RedisKey;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;

@Controller
public class BaseController extends Action {

	/** 用户token */
	protected String token;
	/** 移动唯一设备号，即clinetId */
	private String deviceIdentity;
	/** 版本号 */
	private String version;
	
	protected WebApplicationContext applicationContext = null;
	
	@Autowired
	public RedisService redisService;
	
	@Override
	@ModelAttribute
	public void onStart() {
		
		String token = getRequest().getHeader("token");
		if(Assert.hasTextNull(token)) {
			token = this.getRequest().getParameter("token");
		}
		
		if(Assert.hasTextNull(token)) {
			token = (String)getSessionAttr("token");
		}
		
		this.setToken(token);
	}

	public WebApplicationContext getApplicationContext() {
		if (this.applicationContext == null) {
			this.applicationContext = WebApplicationContextUtils
					.getWebApplicationContext(getServletContext());
		}
		return applicationContext;
	}

	public BaseController() {

	}
	
	
	

	protected HttpServletRequest getRequest() {
		return ((ServletRequestAttributes) RequestContextHolder
				.getRequestAttributes()).getRequest();
	}

	protected HttpSession getSession() {
		return getRequest().getSession();
	}

	/**
	 * 获取登录用户信息
	 * 
	 * @return
	 */
	protected User getUser() {
		return (User) getSessionAttr("User");
	}

	protected String getLoginUserId() {
		User user = (User) getSessionAttr("User");
		if (user == null) {
			return null;
		} else {
			return user.getId();
		}
	}

	protected ServletContext getServletContext() {
		return getSession().getServletContext();
	}

	protected String getPath() {
		return getServletContext().getRealPath("/");
	}

	protected String getPath(String path) {
		return getServletContext().getRealPath(path);
	}

	protected Object getRequestAttr(String key) {
		return getRequest().getAttribute(key);
	}

	protected void setRequestAttr(String key, Object value) {
		getRequest().setAttribute(key, value);
	}

	protected Object getSessionAttr(String key) {
		return getSession().getAttribute(key);
	}
	
	protected void setSessionAttr(String key, Object value) {
		getSession().setAttribute(key, value);
	}

	protected Object getAppAttr(String key) {
		return getServletContext().getAttribute(key);
	}

	protected void setAppAttr(String key, Object value) {
		getServletContext().setAttribute(key, value);
	}

	protected String getReferer() {
		return getRequest().getHeader("referer");
	}
	public String getToken() {
		return token;
	}

	public void setToken(String token) {
		this.token = token;
	}

	public String getDeviceIdentity() {
		return deviceIdentity;
	}

	public void setDeviceIdentity(String deviceIdentity) {
		this.deviceIdentity = deviceIdentity;
	}

	public String getVersion() {
		return version;
	}

	public void setVersion(String version) {
		this.version = version;
	}

	protected String getIpAddr() {

		HttpServletRequest request = getRequest();

		String ip = request.getHeader("x-forwarded-for");
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("X-Forwarded-For");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("X-Real-IP");
		}

		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}

		return ip;
	}

	public String ajax(HttpServletResponse response, String msg) {
		try {
			response.getWriter().print(msg);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	@InitBinder
	protected void initBinder(WebDataBinder binder, WebRequest request) {
		// 日期转换器
		binder.registerCustomEditor(java.util.Date.class, new CustomDateEditor(
				new CustomDateFormat(), true));
	}
	
	protected Map<String, Object> setResponse(Object value) {
        Map<String, Object> response = getMapInstance();
        response.put("response", value);
        return response;
    }
	
	/**
     * 设置响应header
     *
     * @param rc 错误原因
     * @param rm 错误码
     * @return
     */
	protected String error() {
        return toJson(setHeader(ReturnCode.SYSTEM_ERROR.code(),ReturnMessage.SYSTEM_ERROR.message()));
    }
    
    /**
     * 设置响应header
     *
     * @param rc 错误原因
     * @param rm 错误码
     * @return
     */
    protected Map<String,Object> setError() {
        return setHeader(ReturnCode.SYSTEM_ERROR.code(),ReturnMessage.SYSTEM_ERROR.message());
    }
    
    /**
     * 设置响应header
     *
     * @param rc 错误原因
     * @param rm 错误码
     * @return
     */
    protected Map<String,Object> setError(String error) {
        return setHeader(ReturnCode.SYSTEM_ERROR.code(),error);
    }
    
    /**
     * 设置响应header
     *
     * @param rc 错误原因
     * @param rm 错误码
     * @return
     */
    protected String success() {
        return toJson(setHeader(ReturnCode.SUCCESS.code(),ReturnMessage.SUCCESS.message()));
    }
    
    /**
     * 设置响应header
     *
     * @param rc 错误原因
     * @param rm 错误码
     * @return
     */
    protected Map<String,Object> setSuccess() {
        return setHeader(ReturnCode.SUCCESS.code(),ReturnMessage.SUCCESS.message());
    }

    /**
     * 设置响应header
     *
     * @param rc 错误原因
     * @param rm 错误码
     * @return
     */
    protected Map<String, Object> setHeader(int rc, String rm) {
        Map<String, Object> params = getMapInstance();
        Map<String, Object> header = getMapInstance();
        params.put("rc", rc);
        params.put("rm", rm);
        header.put("header", params);
        return setResponse(header);
    }

    /**
     * 设置body值.默认会添加成功的rc和rm
     *
     * @param value
     * @return
     */
    protected Map<String, Object> setBody(Object value) {
        Map<String, Object> header = getMapInstance();
        Map<String, Object> response = getMapInstance();
        header.put("rc", ReturnCode.SUCCESS.code());
        header.put("rm", ReturnMessage.SUCCESS.message());
        response.put("header", header);
        if (value != null) {
            response.put("body", value);
        }
        return setResponse(response);
    }
    
    protected Map<String, Object> getMapInstance() {
        return new LinkedHashMap<String, Object>();
    }
    
    protected String toJson(Object obj) {
    	ObjectMapper objectMapper = new ObjectMapper();   
        try {  
            return objectMapper.writeValueAsString(obj);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return null;  
    }
	
    protected boolean isImage(String suffix) {
		return Arrays.asList(new String[] { "png", "jpg", "gif", "bmp", "webp" }).contains(suffix);
	}

	protected boolean isOffice(String suffix) {
		return Arrays.asList(new String[] { "docx", "doc", "xls", "xlsx", "ppt", "pptx" }).contains(suffix);
	}

	protected boolean isAllow(String suffix) {
		if (StringUtils.isBlank(suffix)) {
			return false;
		}
		String[] allow_suffix = suffix.split(",");
		for (int i = 0; i < allow_suffix.length; i++) {
			if (StringUtils.equals(allow_suffix[i], suffix)) {
				return true;
			}
		}
		return false;
	}
    
    /*******************************************************
     * 获取url请求前缀
     * @explain http://localhost:8080/test
     * @param request request对象
     * @return
     */
    public static String getRequestPrefix(HttpServletRequest request) {
        // 网络协议
        String networkProtocol = request.getScheme();
        // 网络ip
        String ip = request.getServerName(); 
        // 端口号
        int port = request.getServerPort();
        // 项目发布名称
        String urlPrefix = networkProtocol + "://" + ip + ":" + port;
        return urlPrefix;
    }

	/*******************************************************
	 * app端验证是否登录
	 * 
	 * @param session
	 * @return
	 */
	public UserSession validateToken() {
		
		UserSession session = null;
		try {
			if(Assert.hasText(token)) {
				Map<String, Object> map = this.redisService.getMap(token);
				if(map != null && map.get("userId") != null) {
					session = UserSession.class.newInstance();
					BeanUtils.populate(session,map);
					
					this.redisService.expireAt(token, RedisKey.tonkenOutSeconds);
				}
			}
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		}

		return session;
	}
	
	

	/*******************************************************
	 * APP端验证是否登录
	 * 
	 * @param session
	 * @return
	 */
	public UserSession validateToken(String token) {
		
		UserSession session = null;
		try {
			if(Assert.hasText(token)) {
				Map<String, Object> map = this.redisService.getMap(token);
				if(map != null && map.get("userId") != null) {
					session = UserSession.class.newInstance();
					BeanUtils.populate(session,map);
					
					this.redisService.expireAt(token, RedisKey.tonkenOutSeconds);
				}
			}
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		}

		return session;
	}
}
